package com.hunan.api.catv.service.biz.invite;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hunan.api.catv.common.Constants;
import com.hunan.api.catv.entity.dto.InviteHelpPromptDto;
import com.hunan.api.catv.entity.dto.MemberInviteAssetsDto;
import com.hunan.api.catv.entity.dto.MemberInviteRuleDto;
import com.hunan.api.catv.entity.po.*;
import com.hunan.api.catv.entity.vo.MemberVo;
import com.hunan.api.catv.entity.vo.SystemDictVo;
import com.hunan.api.catv.service.ResultService;
import com.hunan.api.catv.service.biz.account.AccountBiz;
import com.hunan.api.catv.service.biz.member.MemberBiz;
import com.hunan.api.catv.service.biz.member.sign.MemberSigninRecordBiz;
import com.hunan.api.catv.service.biz.system.SystemDictBiz;
import com.hunan.api.catv.service.impl.member.assets.MemberAssetsDetailSerivce;
import com.hunan.api.catv.utils.GsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Author: wangchao
 * @Date: 2020/11/16 15:26
 */
@Service
public class MemberInviteBiz extends ResultService {

    private static final Integer INVITATION_ACTIVITY_TYPE = 1;
    private static final String DATE_TIME_FORMAT = "yyyyMMddHHmmss";

    @Autowired
    SystemDictBiz systemDictBiz;

    @Autowired
    MemberBiz memberBiz;

    private static final String MEMBER_INVITE_RULE_KEY = "member_invite_rule";


    @Autowired
    MemberSigninRecordBiz memberSigninRecordBiz;

    @Autowired
    AccountBiz accountBiz;

    @Autowired
    MemberAssetsDetailSerivce memberAssetsDetailSerivce;

    /**
     * 获取用户邀请奖励
     */
    public MemberInviteAssetsDto getMemberAssetsByInvite(Integer memberId) {
        //查询是否开始全局拉新
        MemberInviteRuleDto memberInviteRuleDto = getMemberInviteRule();
        return getMemberAssetsInfo(memberId, memberInviteRuleDto.getRegTime(), memberInviteRuleDto.getAmount());
    }

    /**
     * 校验用户
     */
    private boolean checkMemberInfo(Integer memberId, MemberInviteRuleDto memberInviteRuleDto) {
        if (memberInviteRuleDto.getInviteSwitch()) {
            //为true 针对所有用户
            MemberVo info = memberBiz.info(memberId);
            return info != null;
        } else {
            //判断该用户是否在白名单列表中
            MemberWhitelist memberWhitelist = new MemberWhitelist().selectOne(new QueryWrapper<MemberWhitelist>()
                    .eq(MemberWhitelist.MEMBER_ID, memberId)
                    .eq(MemberWhitelist.STATUS, 1)
                    .eq(MemberWhitelist.DELETED, 1));
            return memberWhitelist != null;
        }
    }

    private MemberInviteAssetsDto getMemberAssetsInfo(Integer memberId, String regTime, String amount) {
        //获取用户邀请成功资产
        MemberAssets memberAssets = new MemberAssets().selectOne(new QueryWrapper<MemberAssets>()
                .eq(MemberAssets.MEMBER_ID, memberId)
                .eq(MemberAssets.ACCOUNT_TYPE, 0));
        BigDecimal totalAssets = memberAssets != null ? memberAssets.getTotalAssets() : new BigDecimal(0);
        //获取用户邀请成功人数
        List<MemberVo> inviteRecordList = memberBiz.getInviteRecordList(memberId, regTime);
        int inviteSuccessNum = (int) inviteRecordList.stream().filter(memberVo -> "2".equals(String.valueOf(memberVo.getInviteesStatus()))).filter(this::checkMemberSign).count();
        //用户还可领取资产(邀请总人数 - 邀请成功人数)
        int i = Math.max((int) inviteRecordList.stream()
                .filter(memberVo -> !"0".equals(String.valueOf(memberVo.getInviteesStatus())))
                /*.filter(memberVo -> {
                    if("2".equals(String.valueOf(memberVo.getInviteesStatus()))){
                        return !checkMemberSign(memberVo);
                    }
                    return true;
                })*/.count() - inviteSuccessNum, 0);
        BigDecimal availableAssets = new BigDecimal(i).multiply(new BigDecimal(amount));
        MemberInviteAssetsDto memberInviteAssetsDto = new MemberInviteAssetsDto();
        memberInviteAssetsDto.setAvailableAssets(availableAssets);
        memberInviteAssetsDto.setTotalAssets(totalAssets);
        memberInviteAssetsDto.setInviteSuccessNum(inviteSuccessNum);
        memberInviteAssetsDto.setInviteAvailableNum(i);
        return memberInviteAssetsDto;
    }

    /**
     * 校验是否签到
     */
    private boolean checkMemberSign(MemberVo memberVo) {
        boolean flag = false;
        MemberSigninRecord memberSigninRecord = new MemberSigninRecord().selectOne(new QueryWrapper<MemberSigninRecord>()
                .eq(MemberSigninRecord.MEMBER_ID, memberVo.getMemberId())
                .eq(MemberSigninRecord.SIGN_TYPE, 0)
        );
        if (memberSigninRecord != null) {
            flag = true;
        }
        return flag;
    }

    /**
     * 获取邀请拉新规则
     */
    private MemberInviteRuleDto getMemberInviteRule() {
        SystemDictVo systemDictVo = systemDictBiz.getByKey(Constants.MEMBER_INVITE_RULE);
        return GsonUtils.fromJson(systemDictVo.getDictValue(), MemberInviteRuleDto.class);
    }


    /**
     * 校验是否开启名单列表
     */
    public boolean checkMemberWhitelist(Integer memberId) {
        MemberInviteRuleDto memberInviteRule = getMemberInviteRule();
        if (memberInviteRule.getInviteSwitch()) {
            //针对所有用户
            MemberVo info = memberBiz.info(memberId);
            return info != null;
        } else {
            //判断该用户是否在白名单列表中
            MemberWhitelist memberWhitelist = new MemberWhitelist().selectOne(new QueryWrapper<MemberWhitelist>()
                    .eq(MemberWhitelist.MEMBER_ID, memberId)
                    .eq(MemberWhitelist.STATUS, 1)
                    .eq(MemberWhitelist.DELETED, 1));
            return memberWhitelist != null;
        }
    }

    /**
     * 邀请记录列表
     */
    public PageInfo<MemberVo> getMemberInviteRecord(int pageNum, int pageSize, Integer memberId, String startTime, String endTime) {
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
            startDateTime = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern(DATE_TIME_FORMAT));
            endDateTime = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern(DATE_TIME_FORMAT));
        }
        //查询是否开始全局拉新
        MemberInviteRuleDto memberInviteRuleDto = getMemberInviteRule();
        if (!(pageNum == 0 && pageSize == 0)) {
            PageHelper.startPage(pageNum, pageSize);
        }
        List<MemberVo> inviteRecordList = memberBiz.getInviteRecordList(memberId, memberInviteRuleDto.getRegTime(), startDateTime, endDateTime);
        for (MemberVo memberVo : inviteRecordList) {
            memberVo.setNewInviteStates(getMemberState(memberVo));
            //手机号脱敏
            memberVo.setPhone(StrUtil.hide(memberVo.getPhone(), 3, 7));
            //用户昵称
            String nickName = memberVo.getNickName();
            memberVo.setNickName(StringUtils.isBlank(nickName) ? "" : nickName.length() < 4 ? nickName : StrUtil.hide(nickName, 1, nickName.length() - 1).replaceAll("\\*", " ").replaceFirst(" ", "**").replaceAll(" ", ""));
        }
        return new PageInfo<>(inviteRecordList);
    }

    /**
     * 获取邀请用户状态
     * 1:已完成注册尚未登录
     * 2:已完成注册且已登录尚未完成签到任务
     * 3:邀请成功
     */
    private Integer getMemberState(MemberVo memberVo) {
        if (memberVo.getInviteesStatus() == 2) {
            //已登录,判断是否签到
            MemberSigninRecord memberSigninRecord = new MemberSigninRecord().selectOne(new QueryWrapper<MemberSigninRecord>()
                    .eq(MemberSigninRecord.MEMBER_ID, memberVo.getMemberId())
                    .eq(MemberSigninRecord.SIGN_TYPE, 0));
            if (memberSigninRecord != null) {
                return 3;
            }
            return 2;
        }
        return 1;
    }

    public boolean checkMemberSign(Integer memberId) {
        MemberSigninRecord memberSigninRecord = new MemberSigninRecord().selectOne(new QueryWrapper<MemberSigninRecord>()
                .eq(MemberSigninRecord.MEMBER_ID, memberId)
                .eq(MemberSigninRecord.SIGN_TYPE, 0));
        return memberSigninRecord != null;
    }

    @Transactional
    public Map<String, Object> recordAndAddMemberAsset(String type, Integer memberId, String deviceId, InviteHelpPromptDto inviteHelpPromptDto) {
        Map<String, Object> result = new HashMap<>();
        boolean memberInvite = memberBiz.checkMemberInvite(memberId);
        if (!memberInvite) {
            result.put("status", false);
            result.put("msg", StringUtils.isNotBlank(inviteHelpPromptDto.getInviteState()) ? inviteHelpPromptDto.getInviteState() : "助力失败，此账号不满足助力条件");
            return result;
        }
        boolean memberRegister = memberBiz.checkMemberRegister(memberId);
        if (!memberRegister) {
            result.put("status", false);
            result.put("msg", StringUtils.isNotBlank(inviteHelpPromptDto.getInviteRegisterTime()) ? inviteHelpPromptDto.getInviteRegisterTime() : "助力失败，此账号不满足助力条件");
            return result;
        }
        boolean firstSign = memberSigninRecordBiz.findFirstSign(memberId);
        if (!firstSign) {
            result.put("status", false);
            result.put("msg", StringUtils.isNotBlank(inviteHelpPromptDto.getFirstSign()) ? inviteHelpPromptDto.getFirstSign() : "助力失败，此账号已签到助力");
            return result;
        }
        boolean firstDevice = memberSigninRecordBiz.findFirstDevice(deviceId);
        if (!firstDevice) {
            result.put("status", false);
            result.put("msg", StringUtils.isNotBlank(inviteHelpPromptDto.getFirstDevice()) ? inviteHelpPromptDto.getFirstDevice() : "助力失败，疑似使用同一设备登录！");
            return result;
        }
        MemberInviteRuleDto memberInviteRule = JSONUtil.toBean(systemDictBiz.getStringByKey(MEMBER_INVITE_RULE_KEY), MemberInviteRuleDto.class);
        if (!memberInviteRule.getInviteAddAssets()) {
            result.put("status", false);
            result.put("msg", StringUtils.isNotBlank(inviteHelpPromptDto.getGameOver()) ? inviteHelpPromptDto.getGameOver() : "助力失败，活动已结束！");
            return result;
        }
        String prizeTotal = memberInviteRule.getPrizeTotal();
        BigDecimal total = Optional.ofNullable(memberAssetsDetailSerivce.getAmountAlreadyInvite()).orElse(BigDecimal.ZERO);
        if (total.compareTo(new BigDecimal(prizeTotal)) >= 0) {
            result.put("status", false);
            result.put("msg", StringUtils.isNotBlank(inviteHelpPromptDto.getPrizeEmpty()) ? inviteHelpPromptDto.getPrizeEmpty() : "来晚啦，奖金已瓜分完毕！");
            return result;
        }
        Integer inviterId = memberBiz.getInviterByMemberId(memberId);
        if (!(memberInviteRule.getInviteSwitch() || existWhiteList(inviterId))) {
            result.put("status", false);
            result.put("msg", StringUtils.isNotBlank(inviteHelpPromptDto.getWhiteList()) ? inviteHelpPromptDto.getWhiteList() : "助力失败，邀请人不是白名单用户");
            return result;
        }
        if (memberInviteRule.getAddAssetsSwitch()) {
            addAssetsAndRecordDetail(memberId, memberInviteRule, inviterId);
        }
        memberSigninRecordBiz.add(memberId, type, deviceId);
        String inviterPhone = findInviterPhone(memberId);
        result.put("status", true);
        String sucesss = "助力成功！";
        if (StringUtils.isNotBlank(inviteHelpPromptDto.getSucesss())) {
            sucesss = inviteHelpPromptDto.getSucesss();
        }
        result.put("msg", sucesss + "（邀请人：" + inviterPhone + "）");
        return result;
    }

    private void addAssetsAndRecordDetail(Integer memberId, MemberInviteRuleDto memberInviteRule, Integer inviterId) {
        MemberAssets memberAssets = new MemberAssets().selectOne(new QueryWrapper<MemberAssets>().eq(MemberAssets.MEMBER_ID, inviterId).eq(MemberAssets.STATUS, 1).eq(MemberAssets.DELETED, 1));
        if (memberAssets == null) {
            memberAssets = new MemberAssets();
            memberAssets.setTotalAmount(BigDecimal.ZERO);
            memberAssets.setTotalAssets(BigDecimal.ZERO);
            memberAssets.setCreateTime(new Date());
            memberAssets.setUpdateTime(new Date());
            memberAssets.setMemberId(inviterId);
            accountBiz.saveMemberAssentsInfo(memberAssets);
        }
        BigDecimal totalAmount = memberAssets.getTotalAmount();
        BigDecimal totalAssets = memberAssets.getTotalAssets();

        BigDecimal addResult = totalAmount.add(BigDecimal.valueOf(Long.parseLong(memberInviteRule.getAmount())));
        BigDecimal addtotalAssetsResult = totalAssets.add(BigDecimal.valueOf(Long.parseLong(memberInviteRule.getAmount())));
        recordAssetsDetail(memberId, inviterId, memberAssets, memberInviteRule.getAmount());
        memberAssets.setTotalAmount(addResult);
        memberAssets.setTotalAssets(addtotalAssetsResult);
        memberAssets.setUpdateTime(new Date());
        memberAssets.updateById();
    }

    private void recordAssetsDetail(Integer memberId, Integer inviterId, MemberAssets memberAssets, String amount) {
        MemberAssetsDetail memberAssetsDetail = new MemberAssetsDetail();
        memberAssetsDetail.setCreateTime(new Date());
        memberAssetsDetail.setMemberAssertId(memberAssets.getId());
        memberAssetsDetail.setMemberId(inviterId);
        memberAssetsDetail.setType(INVITATION_ACTIVITY_TYPE);
        memberAssetsDetail.setVariableAmount("+" + amount + "元");
        memberAssetsDetail.setAmount(new BigDecimal(amount));
        memberAssetsDetail.setReason("拉新活动：用户" + memberId + "助力了用户" + inviterId + "，用户" + inviterId + "的资产增加了" + amount + "元");
        memberAssetsDetail.insert();
    }

    private boolean existWhiteList(Integer inviterId) {
        MemberWhitelist memberWhitelist = new MemberWhitelist().selectOne(new QueryWrapper<MemberWhitelist>().eq(MemberWhitelist.MEMBER_ID, inviterId).eq(MemberWhitelist.STATUS, 1).eq(MemberWhitelist.DELETED, 1));
        return memberWhitelist != null;
    }

    public String findInviterPhone(Integer memberId) {
        String phone = "";
        Member member = new Member().selectOne(new QueryWrapper<Member>().eq(Member.MEMBERID, memberId));
        Integer inviterId = member.getInviter();
        if (inviterId != null && !inviterId.equals(0)) {
            Member inviter = new Member().selectOne(new QueryWrapper<Member>().eq(Member.MEMBERID, inviterId));
            phone = inviter != null && StringUtils.isNotBlank(inviter.getPhone()) ? inviter.getPhone().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2") : "";
        }
        return phone;
    }
}
